﻿using System;
using System.Collections.Generic;
using System.Xml;

namespace WindowServices.Common
{
    public class ConfigHelper:IDisposable
    {
        readonly string _path;
        XmlDocument _doc;

        public ConfigHelper(string path)
        {
            _path = path;
            _doc = new XmlDocument();
            _doc.Load(_path);
        }

        public XmlNodeList GetXmlNodeList(string xPath)
        {
            if (string.IsNullOrEmpty(xPath))
            {
                throw new ArgumentNullException("xPath");
            }

            return _doc.SelectNodes(xPath);
        }

        public XmlNode GetSignleXmlNode(string xPath)
        {
            if (string.IsNullOrEmpty(xPath))
            {
                throw new ArgumentNullException("xPath");
            }

            return _doc.SelectSingleNode(xPath);
        }

        public string GetAttribe(string xPath, string key)
        {
            return GetAttribe(GetSignleXmlNode(xPath), key);
        }

        public string GetAttribe(XmlNode node, string key)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            if (node.Attributes != null && node.Attributes[key] != null)
            {
                return node.Attributes[key].Value;
            }

            return null;
        }

        public string GetInnerText(string xPath)
        {
            return GetInnerText(GetSignleXmlNode(xPath));
        }

        public string GetInnerText(XmlNode node)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            return node.InnerText;
        }

        public void SetOrAddAttribe(string xPath, string key, string value)
        {
            SetOrAddAttribe(GetSignleXmlNode(xPath), key, value);
        }

        public void SetOrAddAttribe(XmlNode node, string key, string value)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            if (node.Attributes != null)
            {
                XmlAttribute attribute = node.Attributes[key];
                if (attribute == null)
                {
                        attribute = node.OwnerDocument.CreateAttribute(key);
                        node.Attributes.Append(attribute);
                }

                attribute.Value = value;
            }
        }

        public void AddNode(string xPath, string name, Dictionary<string, string> dicProperty, string innerText)
        {
            AddNode(GetSignleXmlNode(xPath), name, dicProperty, innerText);
        }

        public void AddNode(XmlNode parent, string name, Dictionary<string, string> dicProperty, string innerText)
        {
            if (parent == null)
            {
                throw new ArgumentNullException("parent");
            }

            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException("name");
            }

            XmlNode node = parent.OwnerDocument.CreateElement(name);

            if (dicProperty != null && dicProperty.Count > 0)
            {
                XmlAttribute attribute;
                foreach (string key in dicProperty.Keys)
                {
                    attribute = parent.OwnerDocument.CreateAttribute(key);
                    attribute.Value = dicProperty[key];
                    node.Attributes.Append(attribute);
                }
            }

            if (!string.IsNullOrEmpty(innerText))
            {
                node.InnerText = innerText;
            }

            parent.AppendChild(node);
        }


        public void DelNode(string xPath)
        {
            XmlNodeList list = GetXmlNodeList(xPath);

            foreach (XmlNode node in list)
            {
                DelNode(node);
            }            
        }        

        public void DelNode(XmlNode node)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            if (node.ParentNode == null)
            {
                return;
            }

            XmlNode parent = node.ParentNode;
            parent.RemoveChild(node);
        }


        public void Save()
        {
            _doc.Save(_path);
        }
        #region IDisposable Members

        public void Dispose()
        {
            if (_doc != null)
            {
                _doc = null;
            }
        }

        #endregion
    }
}
